#ifndef fXMLPARSER_H_
#define fXMLPARSER_H_
#include <e32base.h>
#include "YuebaoBuffer.h"
_LIT(KStrTrue, "true");
_LIT(KStrFalse, "false");

namespace Eaxp
{

    /**
     * Replaces all carriage returns and newlines with whitespace characters and
     * removes any leading/trailing whitespaces, and replaces all consequental
     * whitespaces within the string with a single whitespace.
     */
    void XMLStringTrim( TPtr aPtr );

    class CXmlAttribute : public CBase
    {
    public:
        static CXmlAttribute *NewL( const TDesC & aName, const TDesC & aNamespace, const TDesC & aValue );
        ~CXmlAttribute( );

        const TDesC & GetName( ) const;
        const TDesC & GetNamespace( ) const;
        const TDesC & GetValue( ) const;
    private:
        CXmlAttribute( );
        void ConstructL( const TDesC & aName, const TDesC & aNamespace, const TDesC & aValue );

        // attribute name
        HBufC *iName;

        // attribute name space
        HBufC *iNamespace;

        // attribute value
        HBufC *iValue;
    };
}

using namespace Eaxp;

/**
 * Attribute list type
 */
typedef RPointerArray< Eaxp::CXmlAttribute > RAttributeList;

class MSAXEventListener
{
public:
    virtual void StartElement( const TDesC & aName, const TDesC & aNamespace, const RAttributeList & aAttrList ) = 0;
    virtual void EndElement( const TDesC & aName, const TDesC & aNamespace ) = 0;
    virtual void FreeText( const TDesC & aText ) = 0;
    virtual void ParsingError( const TDesC & aReason ) = 0;
    virtual void Comment( const TDesC & aCommentText ) = 0;
};

struct TEscapedCharMapping
{
    TBuf< 8 > iEscape;
    TChar iChar;
};

// parser constants
const TUint KEquals = '=';
const TUint KLessThan = '<';
const TUint KGreaterThan = '>';
const TUint KNewline = '\n';
const TUint KCarriageReturn = '\r';
const TUint KTab = '\t';
const TUint KSlash = '/';
const TUint KWhitespace = ' ';
const TUint KColon = ':';
const TUint KDoubleQuote = '\"';
const TUint KApostrophe = '\'';
const TUint KQuestionMark = '?';
const TUint KAmpersand = '&';
const TUint KSemicolon = ';';
const TUint KLeftBracket = '[';
const TUint KRightBracket = ']';
const TUint KDash = '-';
// CDATA section tokens
_LIT(KCDataSectionStart, "![CDATA[");
_LIT(KCDataSectionEnd, "]]");
// Comment node tokens
_LIT(KCommentSectionStart, "!--");
_LIT(KCommentSectionEnd, "--");

// parser core states
enum TCoreParserState
{
    ECoreNullState = 1, ECoreParsingElement, ECoreParsingFreeText
};

// attribute list parsing states
enum TAttrParserState
{
    EAttrNullState = 1, EAttrParsingAttrName, EAttrParsingAttrValue
};

// parsing error leave code
const TInt KErrParsingError = 167899;

class fXmlParser : public CBase
{
public:
    static fXmlParser *NewL( MSAXEventListener & aListener );
    static fXmlParser *NewLC( MSAXEventListener & aListener );

    virtual ~fXmlParser( );
    TBool ParseL( const TDesC & aDocument );
    TBool ParseL( const TDesC8 & aDocument );
private:
    explicit fXmlParser( MSAXEventListener & aListener );
    void ConstructL( );
    void AllocateDefaultSizeBuffersL( );
    void AddEscapeMappingL( const TDesC & aEscape, TChar aChar );

    void ParseImplL( );
    void ProcessElementL( const TLex & aLex );
    void ProcessCDATASectionL( TLex & aLex );
    void ProcessCommentSectionL( TLex & aLex );
    TPtrC FindElementNameL( const TPtrC & aElement, TInt & aEndOffset );
    void ParseNameL( const TPtrC & aNameBuf, TPtrC & aName, TPtrC & aNamespace );
    void ParseAttributeListL( const TPtrC & aAttrBuf, RAttributeList & aAttrList, TBool & aEndElement );
    void IllegalCharacterMetL( TChar aChar );
    void ValidateSizeAndCopyL( HBufC ** aTo, const TDesC & aFrom );
    void ValidateSizeL( HBufC ** aBuf, TInt aSize );
    void UnescapeL( const TPtrC & aFrom, TBool aTrim = EFalse );
    TChar FindEscapeL( const TPtrC & aEscape );

    // SAX event listener
    MSAXEventListener & iListener;

    // the document being parsed
    TPtrC iDocument;

    // line number being parsed
    TInt iLineNum;

    // core parser state
    TCoreParserState iCoreState;

    // paring error reason buffer
    YuebaoBuffer< 128 > iErrorReason;

    // attribute parsing resources
    HBufC *iAttrName;
    HBufC *iAttrValue;

    // free text buffer
    HBufC *iFreeText;

    // unescape buffer
    HBufC *iUnescapeBuffer;

    // escape character mapping table
    TEscapedCharMapping *iEscapedCharMap;
    TInt iEscapeMapCapacity;
    TInt iNumEscapeMappings;
};

#endif /*fXMLPARSER_H_ */

